﻿using Newtonsoft.Json;
using River.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZWZTools.BaseUI;

namespace ZWZTools.Forms
{
    public partial class VideoEdit : BaseForm
    {
        string destFile = null;// 目标文件
        decimal duration = 0;// 视频长度
        decimal current_pt = 0;// 分割时当前时间
        int PER_LENGTH = 60;// 分割时长
        StreamsInfo curStream = null;// 音视频信息
        bool showFileInfo = true;/// 显示文件信息标志
        string[] srcFiles = null;// 待处理文件列表
        int cur_file_index = 0;// 当前处理文件序号
        int defaultRate = 8000;// 默认采样率
        bool ffmpegEnable = false; // FFMpeg组件是否可用
        StringBuilder fileInfoBuilder = new StringBuilder(); bool _seperateFlag;
        bool SeperateFlag// 分割音频处理标志
        {
            get { return _seperateFlag; }
            set
            {
                _seperateFlag = value;
            }
        }

        private bool _pcmFlag;// 转换音频处理标志
        private bool ConvertPcmFlag
        {
            get { return _pcmFlag; }
            set
            {
                _pcmFlag = value;
            }
        }
        private bool _wordFlag;// 文字识别处理标志
        private bool ConvertWordFlag
        {
            get { return _wordFlag; }
            set
            {
                _wordFlag = value;
            }
        }


        public VideoEdit()
            : base()
        {
            InitializeComponent();
            cb_AudioFormat.SelectedIndex = 0;

            if (FFmpegUtils.FFmpegOutput == null)
            {
                FFmpegUtils.FFmpegOutput += FFmpegOutput;// 注册事件
            }
            // 读取配置
            //chbShowDetail.Checked = IniUtil.INIGetStringValue(IniSection.Other, IniKey.ShowFileInfo, "0") == "1";
            //showFileInfo = chbShowDetail.Checked;
            //rtbCmd.Text = IniUtil.INIGetStringValue(IniSection.Other, IniKey.FFmpegCmd);
            tbdestRate.Text = IniUtil.INIGetStringValue(IniSection.Other, IniKey.DefaultRate, defaultRate.ToString());
            cb_AudioFormat.Text = IniUtil.INIGetStringValue(IniSection.Other, IniKey.AudioFormat, "m4a");
            //tbTimeLength.Text = IniUtil.INIGetStringValue(IniSection.Other, IniKey.SeperateLength, "600");
        }

        #region 窗口事件

        private void VideoEdit_FormClosed(object sender, FormClosedEventArgs e)
        {
            FormHelper.ShowMain(this);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            string ffmpegPath = FFmpegBinariesHelper.RegisterFFmpegBinaries(false);
            ffmpegEnable = !string.IsNullOrEmpty(ffmpegPath);
            if (!ffmpegEnable) ShowMainStatus("没有发现FFMpeg组件，相关功能不可用");
            // FFmpeg 组件功能
            //btnConvertRate.Enabled = ffmpegEnable;
            //btnExtract.Enabled = ffmpegEnable;
            //btnAudio2Pcm.Enabled = ffmpegEnable;
            //btnExeCmd.Enabled = ffmpegEnable;

            //tbdestRate.Enabled = ffmpegEnable;
            //cb_AudioFormat.Enabled = ffmpegEnable;
            //chbShowDetail.Enabled = ffmpegEnable;
            //tbTimeLength.Enabled = ffmpegEnable;
            //rtbCmd.Enabled = ffmpegEnable;
        }

        #endregion

        /// <summary>
        /// 选择文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Browse_Click(object sender, EventArgs e)
        {
            //tbSampleRate.Text = string.Empty;
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Multiselect = false;
                ofd.RestoreDirectory = true;
                if (ofd.ShowDialog() == DialogResult.OK)
                    tb_FileName.Text = ofd.FileName;
                else
                    return;
            }
            if (Path.GetExtension(tb_FileName.Text).ToLower() != ".pcm")
            {
                btnViewInfo();// 识别信息
            }
        }
        /// <summary>
        /// 查看信息
        /// </summary>
        private void btnViewInfo()
        {
            if (!checkFile() || !ffmpegEnable)
                return;
            fileInfoBuilder.Clear();
            duration = 0;
            ShowStatus("以下是文件信息：");
            FFmpegUtils.Start(FFmpegUtils.Args_ViewInfo(tb_FileName.Text), ViewFinish);
        }
        /// <summary>
        /// 读取信息完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ViewFinish(object sender, EventArgs e)
        {
            FFmpegRetDetail retDetail = JsonConvert.DeserializeObject<FFmpegRetDetail>(fileInfoBuilder.ToString());
            if (retDetail != null && retDetail.streams != null)
            {
                curStream = retDetail.streams.Where(x => x.codec_type == "audio").FirstOrDefault();
                if (curStream != null)
                {
                    Invoke(new Action(() =>
                    {
                        rtb_Status.Text = curStream.sample_rate;
                        decimal.TryParse(curStream.duration, out duration);
                    }));
                }
            }
            else
            {
                ShowStatus("无法识别音频信息", true);
            }
            ShowStatus("读取文件信息完毕.", true);
        }
        /// <summary>
        /// 检测用户选择的文件
        /// </summary>
        /// <returns></returns>
        private bool checkFile()
        {
            string fileName = tb_FileName.Text;

            if (string.IsNullOrEmpty(fileName) || !File.Exists(fileName))
            {
                MsgUtil.Error("请选择有效的音视频文件");
                return false;
            }
            return true;
        }
        /// <summary>
        /// 信息提示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FFmpegOutput(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                fileInfoBuilder.AppendLine(e.Data);
                ShowStatus(e.Data, true, true);
            }
        }

        /// <summary>
        /// 视频中提取音频
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Extract_Click(object sender, EventArgs e)
        {
            if (!checkFile()) return;
            ShowStatus("开始提取音频...");
            string args = null;
            int sampleRate = GetSampleRate(tbdestRate, defaultRate);
            buildDestFileName(tb_FileName.Text, cb_AudioFormat.Text, sampleRate);
            if (cb_AudioFormat.Text == "mp3")
            {
                args = FFmpegUtils.Args_ConvertVideo2mp3(tb_FileName.Text, destFile, sampleRate);
            }
            else if (cb_AudioFormat.Text == "pcm")
            {
                args = FFmpegUtils.Args_ConvertVideo2pcm(tb_FileName.Text, destFile, sampleRate);
            }
            else
                args = FFmpegUtils.Args_ConvertVideo2Audio(tb_FileName.Text, destFile, sampleRate); // 默认m4a
            FFmpegUtils.Start(args, extractFinish);
        }
        private void extractFinish(object sender, EventArgs e)
        {
            ShowStatus("音频转换完成！\r\n音频文件详见：" + destFile, false);
        }

        /// <summary>
        /// 生成自动目标文件名
        /// </summary>
        /// <param name="srcPath">源文件全名</param>
        /// <param name="destExt">目标扩展名</param>
        /// <param name="rate">目标采样率</param>
        /// <returns></returns>
        private bool buildDestFileName(string srcPath, string destExt, int rate)
        {
            string srcExt = Path.GetExtension(srcPath);

            // 如果目标文件类型为空，保留原来的扩展名
            if (string.IsNullOrEmpty(destExt))
            {
                destExt = srcExt;
            }
            destFile = string.Format("{0}_{1}_{2}k.{3}", srcPath.Replace(srcExt, ""), DateTime.Now.ToString("yyMMddHHmmss"), rate / 1000, destExt.TrimStart('.'));
            return true;
        }
        /// <summary>
        /// 读取用户输入采样率
        /// </summary>
        /// <param name="tb"></param>
        /// <returns></returns>
        private int GetSampleRate(TextBox tb, int defaultRate = 0)
        {
            int sampleRate = 0;
            if (!int.TryParse(tb.Text, out sampleRate) || sampleRate == 0)
            {
                ShowStatus("采样率无效，使用默认采样率：" + defaultRate, false);
                return defaultRate;
            }
            return sampleRate;
        }
        /// <summary>
        /// 显示状态信息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="skiptime"></param>
        private void ShowStatus(string msg, bool checkShow = false, bool skiptime = false)
        {
            if (checkShow && !showFileInfo) return;
            this.InvokeDele(new Action(() =>
            {
                rtb_Status.AppendText((skiptime ? "" : Utils.NowTime() + ": ") + msg + "\r\n");
                rtb_Status.Select(rtb_Status.Text.Length, 0);
                rtb_Status.ScrollToCaret();
            }));
        }

        private void btn_BrowseList_Click(object sender, EventArgs e)
        {
            //tbSampleRate.Text = string.Empty;
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Multiselect = true;
                ofd.RestoreDirectory = true;
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    lb_files.Items.Clear();
                    foreach (string FileName in ofd.FileNames)
                    {
                        if (FileName != null)
                        {
                            if (File.Exists(FileName))
                            {
                                lb_files.Items.Add(FileName);
                            }
                        }
                    }
                }
                else
                    return;
            }
            duration = 0;
            for (int i = 0; i < lb_files.Items.Count; i++)
            {
                if (Path.GetExtension(lb_files.Items[i].ToString()).ToLower() != ".pcm")
                {
                    btnViewInfoList(lb_files.Items[i].ToString());// 识别信息
                }
            }

        }
        /// <summary>
        /// 查看信息
        /// </summary>
        private void btnViewInfoList(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                return;
            if (!ffmpegEnable)
                return;
            fileInfoBuilder.Clear();
            ShowStatusList("以下是文件信息：");
            FFmpegUtils.Start(FFmpegUtils.Args_ViewInfo(fileName), ViewsFinish);
            duration++;
        }
        /// <summary>
        /// 显示状态信息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="skiptime"></param>
        private void ShowStatusList(string msg, bool checkShow = false, bool skiptime = false)
        {
            if (checkShow && !showFileInfo) return;
            this.InvokeDele(new Action(() =>
            {
                rtb_Status.AppendText((skiptime ? "" : Utils.NowTime() + ": ") + msg + "\r\n");
                rtb_Status.Select(rtb_Status.Text.Length, 0);
                rtb_Status.ScrollToCaret();
            }));
        }
        /// <summary>
        /// 读取信息完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ViewsFinish(object sender, EventArgs e)
        {
            FFmpegRetDetail retDetail = JsonConvert.DeserializeObject<FFmpegRetDetail>(fileInfoBuilder.ToString());
            if (retDetail != null && retDetail.streams != null)
            {
                curStream = retDetail.streams.Where(x => x.codec_type == "audio").FirstOrDefault();
                if (curStream != null)
                {
                    Invoke(new Action(() =>
                    {
                        rtb_Status.Text = curStream.sample_rate;
                        decimal.TryParse(curStream.duration, out duration);
                    }));
                }
            }
            else
            {
                ShowStatusList("无法识别音频信息", true);
            }
            ShowStatusList("读取文件信息完毕.", true);
        }

        private void btn_ExtractList_Click(object sender, EventArgs e)
        {
            if (!checkFiles()) return;
            ShowStatusList("开始提取音频...");
            string args = null;
            int sampleRate = GetSampleRate(tbdestRate, defaultRate);
            for (int i = 0; i < lb_files.Items.Count; i++)
            {
                buildDestFileName(lb_files.Items[i].ToString(), cb_AudioFormat.Text, sampleRate);
                if (cb_AudioFormat.Text == "mp3")
                {
                    args += FFmpegUtils.Args_ConvertVideo2mp3(lb_files.Items[i].ToString(), destFile, sampleRate) + "\r\n";
                }
                else if (cb_AudioFormat.Text == "pcm")
                {
                    args += FFmpegUtils.Args_ConvertVideo2pcm(lb_files.Items[i].ToString(), destFile, sampleRate) + "\r\n";
                }
                else
                    args += FFmpegUtils.Args_ConvertVideo2Audio(lb_files.Items[i].ToString(), destFile, sampleRate) + "\r\n"; // 默认m4a
            }
            FFmpegUtils.Start(args, extractFinish);
        }
        /// <summary>
        /// 检测用户选择的文件
        /// </summary>
        /// <returns></returns>
        private bool checkFiles()
        {
            if (lb_files.Items.Count == 0)
            {
                MsgUtil.Error("请选择有效的音视频文件");
                return false;
            }
            return true;
        }
    }
}
